#include <cstdlib>
#include <stdio.h>
#include <CL/cl.h>
#include <memory>
#include <vector>

#include "clUtils.h"

using namespace std;

void enumPlatforms() {
	
	cl_uint numPlatforms;
    CL_CHECK(clGetPlatformIDs(0, NULL, &numPlatforms));
    ASSERT(numPlatforms != 0, "No OpenCL platform found");

    vector<cl_platform_id> platformIds(numPlatforms);
    CL_CHECK(clGetPlatformIDs(numPlatforms, &platformIds[0], NULL));

    for (cl_int i = 0; i < numPlatforms; i++) {
		char name[256];
		clGetPlatformInfo(platformIds[i], CL_PLATFORM_NAME, sizeof(name), name, NULL);
		
		printf("platform %d: %s\n", i + 1, name);
		
        cl_uint numDevices;
        CL_CHECK(clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices));
        if (numDevices == 0) continue;

        vector<cl_device_id> devices(numDevices);
        CL_CHECK(clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_ALL, numDevices, &devices[0], NULL));
		
		for (cl_int devIndex = 0; devIndex < numDevices; devIndex++) {			
			CL_CHECK(clGetDeviceInfo(devices[devIndex], CL_DEVICE_NAME, sizeof(name), name, NULL));
			
			cl_device_type type;
			CL_CHECK(clGetDeviceInfo(devices[devIndex], CL_DEVICE_TYPE, sizeof(type), &type, NULL));
			
			string typeStr;
			if (type & CL_DEVICE_TYPE_CPU) {
				typeStr += "CPU ";
			}
			if (type & CL_DEVICE_TYPE_GPU) {
				typeStr += "GPU ";
			}
			if (type & CL_DEVICE_TYPE_ACCELERATOR) {
				typeStr += "Accelerator";
			}
			
			printf("	device %d %s type=%s\n", devIndex + 1, name, typeStr.c_str());
		}
    }
}

int main(int argc, char** argv) {
    
	try {
		enumPlatforms();
	} catch (Exception& e) {
		printf("ERROR: %s\n", e.what());
	}
    
    return 0;
}

